package org.dromara.workflow.flowable.cmd;

import cn.hutool.core.collection.CollUtil;
import org.dromara.common.core.domain.dto.OssDTO;
import org.dromara.common.core.service.OssService;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.persistence.entity.AttachmentEntity;
import org.flowable.engine.impl.persistence.entity.AttachmentEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;

import java.util.Date;
import java.util.List;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：附件上传
 */
/**
 * 附件命令类，实现了一个命令接口，用于处理与附件相关的操作
 * 该类通过实现Command接口，可以对附件进行特定的处理，这里特指执行一个返回Boolean的结果的操作
 */
public class AttachmentCmd implements Command<Boolean> {

    /**
     * 文件ID，标识唯一文件资源，用于后续对文件的引用和操作
     */
    private final String fileId;

    /**
     * 任务ID，用于跟踪和标识特定的处理任务，确保任务的唯一性和可追溯性
     */
    private final String taskId;

    /**
     * 流程实例ID，用于在流程引擎中唯一标识一个流程实例，支持流程的跟踪和管理
     */
    private final String processInstanceId;

    /**
     * 对象存储服务，用于处理与对象存储相关的操作，如文件的上传、下载和删除等
     */
    private final OssService ossService;

    /**
     * 构造AttachmentCmd类的实例
     * 该构造函数主要用于初始化AttachmentCmd对象的相关属性，包括文件ID、任务ID、流程实例ID和OSS服务对象
     *
     * @param fileId          文件的唯一标识符，用于识别和操作特定的文件
     * @param taskId          任务的唯一标识符，关联了特定的业务任务
     * @param processInstanceId 流程实例的唯一标识符，用于标识和管理一个流程实例
     * @param ossService      提供对象存储服务的实例，用于处理文件的存储和检索
     */
    public AttachmentCmd(String fileId, String taskId, String processInstanceId, OssService ossService) {
        this.fileId = fileId;
        this.taskId = taskId;
        this.processInstanceId = processInstanceId;
        this.ossService = ossService;
    }

    /**
     * 执行命令，将指定的OSS文件添加为附件
     *
     * @param commandContext 命令上下文对象，包含执行所需的各种上下文信息
     * @return 执行结果，成功返回true，失败返回false
     */
    @Override
    public Boolean execute(CommandContext commandContext) {
        try {
            // 检查文件ID是否已指定，若未指定则不执行任何操作
            if (StringUtils.isNotBlank(fileId)) {
                // 根据文件ID列表从OSS服务中选择对应的文件信息
                List<OssDTO> ossList = ossService.selectByIds(fileId);
                // 确保查询到的OSS文件列表不为空
                if (CollUtil.isNotEmpty(ossList)) {
                    // 遍历OSS文件列表，为每个文件创建并保存附件实体
                    for (OssDTO oss : ossList) {
                        // 获取附件实体管理器
                        AttachmentEntityManager attachmentEntityManager = CommandContextUtil.getAttachmentEntityManager();
                        // 创建一个新的附件实体
                        AttachmentEntity attachmentEntity = attachmentEntityManager.create();
                        // 初始化附件实体的属性
                        attachmentEntity.setRevision(1); // 修订版设为1，表示初始版本
                        attachmentEntity.setUserId(LoginHelper.getUserId().toString()); // 设置上传用户ID
                        attachmentEntity.setName(oss.getOriginalName()); // 设置附件名称为OSS文件的原始名称
                        attachmentEntity.setDescription(oss.getOriginalName()); // 设置附件描述为OSS文件的原始名称
                        attachmentEntity.setType(oss.getFileSuffix()); // 设置附件类型为文件后缀
                        attachmentEntity.setTaskId(taskId); // 关联任务ID
                        attachmentEntity.setProcessInstanceId(processInstanceId); // 关联流程实例ID
                        attachmentEntity.setContentId(oss.getOssId().toString()); // 设置附件内容ID为OSS文件ID
                        attachmentEntity.setTime(new Date()); // 设置附件创建时间为当前时间
                        // 插入附件实体到数据库
                        attachmentEntityManager.insert(attachmentEntity);
                    }
                }
            }
        } catch (Exception e) {
            // 捕获并抛出运行时异常，确保异常不会被静默处理
            throw new RuntimeException(e);
        }
        // 返回执行成功标志
        return true;
    }
}
